package bio.chatproject.server;

import bio.chatproject.util.Constants;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Set;

/**
 * @author charwayH
 * 服务端线程
 */
public class ServerReader extends Thread {
    private Socket socket;

    public ServerReader(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        DataInputStream dis = null;
        try {
            dis = new DataInputStream(socket.getInputStream());
            // 1.循环一直等待客户端的消息
            while (true) {
                // 2.当前读取的消息类型:1登录，2群发 @消息，3私发
                int flag = dis.readInt();
                if (flag == 1) {
                    // 先将当前登录的客户端socket存放到在线人数的socket集合中
                    String name = dis.readUTF();
                    System.out.println(name + "----->" + socket.getRemoteSocketAddress());
                    ServerChat.onlineSockets.put(socket, name);
                }
                writeMsg(flag, dis);
            }
        } catch (IOException e) {
            System.out.println("====有人下线====");
            // 从在线人数中将当前socket移除出去
            ServerChat.onlineSockets.remove(socket);
            try {
                // 重新更新在线人数并发给所有客户端
                writeMsg(1, dis);
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }

    private void writeMsg(int flag, DataInputStream dis) throws IOException {
        String msg;
        if (flag == 1) {
            /**
             * 读取所有在线人数发送给所有客户端去更新自己的在线人数
             */
            StringBuilder sb = new StringBuilder();
            Collection<String> onlineNames = ServerChat.onlineSockets.values();
            // 判断是否存在在线人数
            if (onlineNames != null && onlineNames.size() > 0) {
                for (String name : onlineNames) {
                    sb.append(name + Constants.SPILIT);
                }
                // 去掉最后一个分割符
                msg = sb.substring(0, sb.lastIndexOf(Constants.SPILIT));

                // 叫消息发送给所有客户端
                sendMsgToAll(flag, msg);
            }
        } else if (flag == 2 || flag == 3) {
            // 读到消息，群发或@消息
            // 消息
            String newMsg = dis.readUTF();
            // 得到发件人
            String sendName = ServerChat.onlineSockets.get(socket);

            // 内容
            StringBuilder msgFinal = new StringBuilder();
            // 时间
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EEE");
            if (flag == 2) {
                // 发送者在什么时间说了什么话
                msgFinal.append(sendName).append("    ").append(sdf.format(System.currentTimeMillis() * 2)).append("\r\n");
                msgFinal.append("    ").append(newMsg).append("\r\n");
                sendMsgToAll(flag, msgFinal.toString());
            } else if (flag == 3) {
                msgFinal.append(sendName).append("    ").append(sdf.format(System.currentTimeMillis() * 2)).append("对您私发\r\n");
                msgFinal.append("    ").append(newMsg).append("\r\n");
                // 私发
                // 得到给谁私发
                String destName = dis.readUTF();
                sendMsgToOne(destName, msgFinal.toString());
            }
        }

    }

    private void sendMsgToOne(String destName, String msg) throws IOException {
        // 拿到所有的在线socket管道  给这些管道写出信息
        Set<Socket> allOnlineSockets = ServerChat.onlineSockets.keySet();
        for (Socket sk : allOnlineSockets) {
            // 得到昂前需要私发的socket
            // 只对这个名字对应的socket私发消息
            if (ServerChat.onlineSockets.get(sk).trim().equals(destName)) {
                DataOutputStream dos = new DataOutputStream(sk.getOutputStream());
                // 消息类型
                dos.writeInt(2);
                dos.writeUTF(msg);
                dos.flush();
            }
        }
    }

    private void sendMsgToAll(int flag, String msg) throws IOException {
        // 拿到所有的在线socket管道，给这些管道写出消息
        Set<Socket> allOnlineSockets = ServerChat.onlineSockets.keySet();
        for (Socket sk : allOnlineSockets) {
            DataOutputStream dos = new DataOutputStream(sk.getOutputStream());
            // 消息类型
            dos.writeInt(flag);
            // 消息内容
            dos.writeUTF(msg);
            dos.flush();
        }
    }
}
